home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / Object.C < prev    next >
C/C++ Source or Header  |  1990-12-19  |  11KB  |  523 lines

  1. //$Object,ChangeMessage,FindMember$
  2. #include "Object.h"
  3. #include "OrdColl.h"
  4. #include "IdDictionary.h"
  5. #include "ObjInt.h"
  6. #include "Error.h"
  7. #include "String.h"
  8. #include "Storage.h"
  9. #include "ProgEnv.h"
  10. #include "System.h"
  11. #include "ObjectTable.h"
  12. #include "ClassManager.h"
  13. #include "AccessMem.h"
  14. #include "IO/membuf.h"
  15.  
  16. bool gInPrintOn;
  17. bool gAddToInstTable= TRUE;
  18.  
  19. extern void InitProgenv();
  20.   
  21. //---- observing ---------------------------------------------------------
  22.  
  23. static IdDictionary *Observer; 
  24. // dictionary associating a list of observers with an Object
  25.  
  26. static IdDictionary *DelayedChanges; 
  27. // dictionary to store the delayed Change messages, the key is the object pointer
  28. // (IdDictionary) the value is an OrderedCollection of ChangeMessages (see below).
  29. // The first entry of the OrderedCollection is a reference count of the number of
  30. // DelayChanges requests. FlushChanges will be executed when the count drops to 0.
  31. // Whether change messages are delayed is set with the cObjDelayChanges flag
  32.  
  33.  
  34. struct ChangeMessage: public Object {
  35.     void *what;
  36.     int part, id;
  37.  
  38.     ChangeMessage(void *w, int p, int i)
  39.     { what= w; part= p; id= i; }
  40. };
  41.  
  42. //---- automatically added by macro metaImpl -----------------------------------
  43.  
  44. static Class ObjectClassMetaImpl0("Object",
  45.                   sizeof (Object),
  46.                   new Object((_dummy*)0),
  47.                   __FILE__,
  48.                   "./Object.h",
  49.                   __LINE__,
  50.                   1,
  51.                   TRUE);
  52.  
  53. Object::Object(class _dummy*)
  54. {
  55.     flags= cObjNonDeleted | cObjIsProto;
  56.     isa= &ObjectClassMetaImpl0;
  57.     ObjectClassMetaImpl0.SetSuper();
  58. }
  59.  
  60. Class *Object::IsA()
  61. {
  62.     return &ObjectClassMetaImpl0;
  63. }
  64.  
  65. void Object::Members()
  66. {
  67.     TheThis= this;
  68.     D_F(TX(flags), 0);    
  69. }
  70.  
  71. //---- ordinary methods ----------------------------------------------------
  72.  
  73. Object::Object(int f)
  74. {
  75.     flags= (f & cFlagMask) | cObjNonDeleted;
  76.     ObjectTable::Add(this);
  77. }
  78.  
  79. Object::~Object()
  80. {
  81.     if (! TestFlag(cObjNonDeleted)) {
  82.     if (gDebug)
  83.         Fatal("~Object", "object deleted twice");
  84.     return;
  85.     }
  86.   
  87.     ObjectTable::Remove(this);
  88.     flags&= ~cObjNonDeleted;
  89.     if (gInPrintOn) 
  90.     gClassManager->InvalidatePtr(this);
  91.     
  92.     if (IsObserved()) {
  93.     Collection *observers= GetObservers(); // GetObservers is statically bound!!!
  94.     flags &= ~cObjIsObserved;
  95.     if (observers)
  96.         CleanupObservers(observers);
  97.     }
  98. }
  99.  
  100. void Object::FreeAll()
  101. {
  102. }
  103.  
  104. char *Object::ClassName()
  105. {
  106.     return IsA()->Name();
  107.  
  108. ObjPtr Object::New()
  109. {
  110.     return IsA()->New();
  111. }
  112.  
  113. void Object::InitNew()
  114. {
  115. }
  116.  
  117. void Object::Inspect(bool block)
  118. {
  119.     InitProgenv();
  120.     gProgEnv->InspectObject(this, block);
  121. }
  122.  
  123. void Object::EditSource(bool definition)
  124. {
  125.     InitProgenv();
  126.     gProgEnv->EditSourceOf(IsA(), definition);
  127. }
  128.  
  129. void Object::InspectorId(char *buf, int)
  130. {
  131.     buf= "";
  132. }
  133.  
  134. void Object::Parts(class Collection *)
  135. {
  136. }
  137.  
  138. void Object::DoError(int level, char *location, char *fmt, va_list va)
  139. {
  140.     ::ErrorHandler(level, form("%s::%s", ClassName(), location), fmt, va);
  141. }
  142.  
  143. void Object::Error(char *location, char *va_(fmt), ...)
  144. {
  145.     va_list ap;
  146.     va_start(ap,va_(fmt));
  147.     DoError(cError, location, va_(fmt), ap);
  148.     va_end(ap);
  149. }
  150.  
  151. void Object::SysError(char *location,  char *va_(fmt), ...)
  152. {
  153.     va_list ap;
  154.     va_start(ap,va_(fmt));
  155.     DoError(cSysError, location, va_(fmt), ap);
  156.     va_end(ap);
  157. }
  158.  
  159. void Object::Warning(char *location, char *va_(fmt), ...)
  160. {
  161.     va_list ap;
  162.     va_start(ap,va_(fmt));
  163.     DoError(cWarning, location, va_(fmt), ap);
  164.     va_end(ap);
  165. }
  166.  
  167. void Object::Fatal(char *location, char *va_(fmt), ...)
  168. {
  169.     va_list ap;
  170.     va_start(ap,va_(fmt));
  171.     DoError(cFatal, location, va_(fmt), ap);
  172.     va_end(ap);
  173. }
  174.  
  175. Object *Object::Clone()
  176. {
  177.     Object *clone= New();
  178.  
  179.     if (clone)
  180.     BCOPY((byte*) this, (byte*) clone, IsA()->Size());
  181.     return clone;
  182. }
  183.  
  184. Object *Object::DeepClone()
  185. {
  186.     int status;
  187.     membuf mb;
  188.     ostream to(&mb);
  189.     istream from(&mb);
  190.     ObjPtr op;
  191.  
  192.     gClassManager->Reset();
  193.     gInPrintOn= TRUE;
  194.     to << this NL;
  195.     to.flush();
  196.     gInPrintOn= FALSE;
  197.     
  198.     gClassManager->Reset();
  199.     from >> op;
  200.     if (status= gClassManager->Reset()) {
  201.     Error("DeepClone", "status %d", status);
  202.     return 0;
  203.     }
  204.     return op;
  205. }
  206.  
  207. void Object::SetFlag(int f, bool b)
  208. {
  209.     if (b)
  210.     SetFlag(f);
  211.     else
  212.     ResetFlag(f);
  213. }
  214.  
  215. //---- fire walls ----------------------------------------------------------
  216.  
  217. void Object::AbstractMethod(char *method)
  218. {
  219.     Warning(method, "abstract method called"); 
  220. }
  221.  
  222. void Object::MayNotUse(char *method)
  223. {
  224.     Warning(method, "not allowed to use this method");
  225. }
  226.  
  227. Object *Object::guard(Class *should)
  228. {
  229.     if (this != 0 && IsA()->isKindOf(should))
  230.     return this;
  231.     Error("Guard", "object is not a %s but a %s", should->Name(), ClassName());
  232.     return 0;
  233. }
  234.  
  235. //---- comparing -----------------------------------------------------------
  236.  
  237. u_long Object::Hash () 
  238. {
  239.     return (u_long) this;
  240. }
  241.  
  242. bool Object::IsEqual (Object *anOp)
  243. {
  244.      return anOp == this;
  245. }
  246.  
  247. int Object::Compare (Object*)
  248. {
  249.     AbstractMethod ("Compare");
  250.     return 0;
  251. }
  252.  
  253. //---- Object Observing --------------------------------------------------------
  254.  
  255. void Object::AddObserver (ObjPtr op)
  256. {
  257.     Collection *observer;
  258.     
  259.     if (op) {
  260.     if (!IsObserved() || ((observer= GetObservers()) == 0)) {
  261.         flags |= cObjIsObserved; 
  262.         observer= MakeObserverColl();
  263.     } else {
  264.         if (observer->FindPtr(op)) {
  265.         Warning("AddObserver", "duplicate in observers");
  266.         return;
  267.         }
  268.     }
  269.     observer->Add (op);
  270.     }
  271. }
  272.  
  273. ObjPtr Object::RemoveObserver (ObjPtr op)
  274. {
  275.     if (this && IsObserved()) {
  276.     Collection *observers= GetObservers();
  277.     if (observers) {
  278.         if (op) 
  279.         op= observers->RemovePtr(op);
  280.         if (observers->IsEmpty()) {
  281.         flags &= ~cObjIsObserved;
  282.         DestroyObserverColl();
  283.         }
  284.         return op;
  285.     }
  286.     }
  287.     return 0;
  288. }
  289.  
  290. void Object::Send(int id, int part, void *vp)
  291. {
  292.     if (!IsObserved())
  293.     return;
  294.     if (TestFlag(cObjDelayChanges)) {
  295.     if (DelayedChanges == 0)
  296.         ObjectTable::AddRoot(DelayedChanges= new IdDictionary);
  297.     Collection *col= (Collection*) DelayedChanges->AtKey(this);
  298.     if (!col)
  299.         Error("Send", "No collection for change messages, %s", ClassName());
  300.     col->Add(new ChangeMessage(vp, part, id));
  301.     DelayedChanges->AtKeyPut(this,col);
  302.     } else {
  303.     Collection *observers= GetObservers();
  304.     if (observers)
  305.         observers->ForEach(Object,DoObserve)(id, part, vp, this);
  306.     }
  307. }
  308.  
  309. void Object::DoObserve(int id, int part, void *vp, Object *op)
  310. {
  311. }
  312.  
  313. void Object::DelayChanges()
  314. {
  315.     flags |= cObjDelayChanges;
  316.     if (DelayedChanges == 0)
  317.     ObjectTable::AddRoot(DelayedChanges= new IdDictionary);
  318.     Collection *col= (Collection*) DelayedChanges->AtKey(this);
  319.     if (!col) {
  320.     col= new OrdCollection;
  321.     col->Add(new ObjInt(0));
  322.     DelayedChanges->AtKeyPut(this,col);
  323.     } else { // increment reference count
  324.     ObjInt *ref= (ObjInt*)col->At(0);
  325.     (*ref)++;
  326.     }
  327. }
  328.  
  329. void Object::FlushChanges()
  330. {
  331.     if (DelayedChanges == 0)
  332.     ObjectTable::AddRoot(DelayedChanges= new IdDictionary);
  333.     Collection *col= (Collection*) DelayedChanges->AtKey(this);
  334.     if (col) {
  335.     ObjInt *ref= (ObjInt*)col->At(0);
  336.     if (ref->GetValue() == 0) {
  337.         flags &= ~cObjDelayChanges;
  338.         ChangeMessage *cm;
  339.         Iter next(col);
  340.         next(); // overread reference count
  341.         while (cm= (ChangeMessage*) next()) 
  342.         Send(cm->id, cm->part, cm->what);
  343.         col->FreeAll();
  344.         Object *tmp= DelayedChanges->RemoveKey(this);
  345.         delete tmp;
  346.     } else 
  347.         (*ref)--;
  348.     }   
  349. }
  350.  
  351. class Iterator *Object::GetObserverIter()        
  352. {
  353.     if (!IsObserved())
  354.     return 0;
  355.     Collection *observers= GetObservers(); 
  356.     if (observers)
  357.     return observers->MakeIterator();
  358.     return 0;
  359. }
  360.  
  361. bool Object::PrintOnWhenObserved(Object*)
  362. {
  363.     return TRUE;    
  364. }
  365.  
  366. Collection *Object::MakeObserverColl()
  367. {
  368.     if (Observer == 0)
  369.     ObjectTable::AddRoot(Observer= new IdDictionary(70));
  370.     Collection *cp= new OrdCollection;
  371.     Observer->AtKeyPut(this, cp);
  372.     return cp;
  373. }
  374.  
  375. Collection *Object::GetObservers()
  376. {
  377.     if (Observer == 0) {
  378.     Warning("GetObservers", "without SetObserver");
  379.     return 0;
  380.     }      
  381.     Collection *cp= (Collection*) Observer->AtKey(this);
  382.     if (cp == 0) 
  383.     Warning("GetObservers", "observers = 0 in GetObservers for %s", ClassName());
  384.     return cp;
  385. }
  386.  
  387. void Object::DestroyObserverColl()
  388. {
  389.     Assoc *op= (Assoc*)Observer->RemoveKey(this);
  390.     Object *observers= op->Value();
  391.     if (observers == 0)
  392.     Warning ("DestroyObserverColl", "0 in DestroyObserverColl() for %s", ClassName());
  393.     SafeDelete(op);
  394.     SafeDelete(observers);
  395. }
  396.  
  397. void Object::SetObserverColl(Collection *cp)
  398. {
  399.     Object *op= Observer->RemoveKey(this);
  400.     SafeDelete(op);
  401.     Observer->AtKeyPut(this, cp);        
  402. }
  403.  
  404. void Object::CleanupObservers(Collection *observers)
  405. {
  406.     observers->ForEach(Object,DoObserve)(-1, cPartSenderDied, 0, this);
  407.     DestroyObserverColl();
  408. }
  409.  
  410. IdDictionary *ObjectGetObservers()
  411. {
  412.     return Observer;
  413. }
  414.  
  415. //---- converting --------------------------------------------------------------
  416.  
  417. char* Object::AsString()
  418. {
  419.     return "";
  420. }
  421.  
  422. //---- activation/passivation --------------------------------------------------
  423.  
  424. static bool printOnWhenObserved(ObjPtr, ObjPtr op, Object *from)
  425. {
  426.     return op->PrintOnWhenObserved(from);
  427. }
  428.  
  429. ostream &Object::PrintOn(ostream &os)
  430. {
  431.     Collection *selectedDeps= 0;
  432.         
  433.     IsA()->MakeIndex(this);
  434.     if (IsObserved()) {
  435.     Collection *observers= GetObservers();
  436.     if (observers->IsEmpty()) { // impossible ??
  437.         flags &= ~cObjIsObserved;
  438.         DestroyObserverColl();
  439.     } else {
  440.         selectedDeps= observers->Select((BoolFun)printOnWhenObserved, this);
  441.         if (selectedDeps->IsEmpty())
  442.         SafeDelete(selectedDeps);
  443.     }
  444.     }
  445.     os << (flags & cFlagMask) SP << selectedDeps SP;
  446.     SafeDelete(selectedDeps);
  447.     return os;
  448. }
  449.  
  450. ostream &operator<< (ostream& s, ObjPtr p)
  451. {
  452.     return gClassManager->SavePtr(s, p);
  453. }
  454.  
  455. istream &LoadPtr(istream &s, Object *&op, Class *cl)
  456. {
  457.     return gClassManager->LoadPtr(s, op, cl);
  458. }
  459.  
  460. istream &Object::ReadFrom(istream &is)
  461. {
  462.     int f;
  463.     Collection *observers;
  464.     
  465.     IsA()->MakeIndex(this);
  466.     is >> f >> observers;
  467.     SetFlag(f);
  468.     if (observers) {
  469.     flags |= cObjIsObserved;
  470.     SetObserverColl(observers);
  471.     }
  472.     return is;
  473. }
  474.  
  475. ostream &Object::DisplayOn(ostream &o)
  476. {
  477.     return o NL;
  478. }
  479.  
  480. //---- FindMember --------------------------------------------------------------
  481.  
  482. class FindMember: public AccessMembers {
  483. public:
  484.     const char *lookfor;
  485.     short offset;
  486.     int len;
  487.     int type;
  488.     Object *op;
  489.     Class *classp;
  490.     
  491.     FindMember(Object *in, const char *name)
  492.     { offset= -1; op= in; lookfor= name; type= 0; len= -1;}
  493.     void Member(char *name, short offset, short lenOrOffset, int type, Class*);
  494. };
  495.  
  496. void FindMember::Member(char *name, short o, short l, int t, Class *c)
  497. {
  498.     if (strcmp(name, lookfor) == 0) {
  499.     offset= o;
  500.     type= t;
  501.     classp= c;
  502.     if (l == -1)
  503.         len= GetLength(op, l, t);
  504.     }
  505. }
  506.  
  507. //---- interface for accessing instance variables by name will be improved
  508. //     in a next release
  509.  
  510. void *Object::GetAddrOf(const char *name, Class *&cl)
  511. {
  512.     FindMember m(this, name);
  513.     IsA()->EnumerateMembers(&m);
  514.     if (m.offset != -1) {
  515.     cl= m.classp;
  516.     return (void*) ((u_long) this + (u_long) m.offset);
  517.     }
  518.     else
  519.     return 0;
  520. }
  521.  
  522.